package com.mainbo.modular.system.model.meta;

import com.alibaba.druid.support.json.JSONUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.mainbo.core.common.constant.Const;
import com.mainbo.modular.system.dao.PtConfigMapper;
import com.mainbo.modular.system.dao.PtOrgMapper;
import com.mainbo.modular.system.model.PtConfig;
import com.mainbo.modular.system.model.PtOrg;
import com.mainbo.modular.system.model.meta.vo.Meta;
import jdk.nashorn.internal.runtime.regexp.joni.Config;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.*;

/**
 * @author moshang
 * @date 2020-02-25
 **/
public  abstract class DefaultMetaProvider implements MetaProvider{

    protected static final Logger logger = LoggerFactory.getLogger(DefaultMetaProvider.class);
    protected static final String COMMA = ",";

    @Resource
    private PtConfigMapper configMapper;
    @Resource
    protected PtOrgMapper orgMapper;

    @Override
    public List<Meta> listAll() {
       EntityWrapper<PtConfig> model = new EntityWrapper<>();
        model.eq("code",getCode());
        model.eq("type",getType());
        model.eq("enable",1);
        model.orderBy("sort",true);
        List<Meta> metaList = new ArrayList<>();
        metaList.addAll(configMapper.selectList(model));
        return metaList;
    }

    @Override
    public List<Meta> listAll(PtConfig model) {
        EntityWrapper<PtConfig> model1 = new EntityWrapper<>();
        if (model.getOrgId()==null){
            model.setOrgId(Const.DEFAULT_ORG_ID);
        }
        model1.eq("org_id",model.getOrgId());
        model1.eq("code",model.getCode());
        model1.eq("type",model.getType());
        model1.eq("enable",1);
        if (model.getAreaId()!=null){
            model1.eq("area_id",model.getAreaId());
        }
        if (model.getSubjectId()!=null){
            model1.eq("subject_id",model.getSubjectId());
        }
        if (model.getGradeId()!=null){
            model1.eq("grade_id",model.getGradeId());
        }
        if (model.getPhase()!=null){
            model1.eq("phase",model.getPhase());
        }
        model1.orderBy("sort",true);

        List<Meta> metaList = new ArrayList<>();
        metaList.addAll(configMapper.selectList(model1));
        return metaList;
    }
    @Override
    public List<Meta> listAllNoOrg(PtConfig model) {
        EntityWrapper<PtConfig> model1 = new EntityWrapper<>();
        model1.eq("code",model.getCode());
        model1.eq("type",model.getType());
        model1.eq("enable",1);
        if (model.getPhase()!=null){
            model1.eq("phase",model.getPhase());
        }
        model1.orderBy("sort",true);
        List<Meta> metaList = new ArrayList<>();
        metaList.addAll(configMapper.selectList(model1));
        return metaList;
    }
    @Override
    public PtConfig listOne(EntityWrapper<PtConfig> model) {
        List<PtConfig> list=configMapper.selectList(model);
        return list != null && list.size() > 0 ? list.get(0) : null;
    }
    @Override
    public Meta getMeta(Integer id) {
        return (Meta) getConfig(id);
    }

    @Override
    public Meta getMeta(String code, String type) {
        PtConfig model = new PtConfig();
        model.setCode(code);
        model.setType(type);
        model.setEnable(1);
        return (Meta) configMapper.selectOne(model);
    }
    @Override
    public Meta getMeta(String code,String value, String type) {
        PtConfig model = new PtConfig();
        model.setCode(code);
        model.setType(type);
        model.setValue(value);
        model.setEnable(1);
        return (Meta) configMapper.selectOne(model);
    }
    protected PtConfig getConfig(Integer id) {
        return configMapper.selectById(id);
    }

    /**
     *
     * @param model
     *          Config
     * @return Config
     */
    public PtConfig getSysConfig(PtConfig model) {
        return configMapper.selectOne(model);
    }

    @Override
    public PtConfig getSysConfigByPhaseId(Integer phaseId) {
        PtConfig model = new PtConfig();
        model.setType(getType());
        model.setCode(getCode());
        model.setPhase(phaseId);
        return configMapper.selectOne(model);
    }

    /**
     * 获取所有年级元数据
     *
     * @return List
     */
    public List<Meta> listGradeMeta() {
        EntityWrapper<PtConfig> model = new EntityWrapper<>();
        model.eq("code",ConfigConstants.SYS_GRADE_CODE);
        model.eq("type",ConfigConstants.SYS_TYPE);
        model.eq("enable",1);
        model.orderBy("sort",true);
        List<Meta> metaList = new ArrayList<>();
        metaList.addAll( configMapper.selectList(model));
        return metaList;
    }

    @Override
    public List<Meta> listMeta(String code, String type) {
        EntityWrapper<PtConfig> model = new EntityWrapper<>();
        model.eq("code",code);
        model.eq("type",type);
        model.eq("enable",1);
        model.orderBy("sort",true);
        List<Meta> metaList = new ArrayList<Meta>();
        metaList.addAll( configMapper.selectList(model));
        return metaList;
    }
    @Override
    public List<Meta> listMeta(String code, String type,String orgId) {
        EntityWrapper<PtConfig> model = new EntityWrapper<>();
        model.eq("code",code);
        model.eq("type",type);
        model.eq("enable",1);
        model.eq("org_id",orgId);
        model.orderBy("sort",true);
        List<Meta> metaList = new ArrayList<Meta>();
        metaList.addAll(configMapper.selectList(model));
        return metaList;
    }
    protected PtConfig getOne(PtConfig model) {
        return configMapper.selectOne(model);
    }

    protected abstract String getCode();

    // 默认查询系统数据
    protected String getType() {
        return ConfigConstants.SYS_TYPE;
    }
    @Component("phaseProvider")
    public static class DefaultPhaseProvider extends DefaultMetaProvider implements PhaseProvider {

        @Override
        public List<Meta> listAllPhase() {
            return listAll();
        }

        @Override
        protected String getCode() {
            return ConfigConstants.SYS_PHASE_CODE;
        }

    }
    @Component("phaseSubjectProvider")
    public static class DefaultPhaseSubjectProvider extends DefaultMetaProvider implements PhaseSubjectProvider {

        @Override
        public List<Meta> listAllSubject(Integer id) {
            Meta metaShip = super.getMeta(id);
            List<Meta> configList = new ArrayList<Meta>();
            String[] ids = StringUtils.split(metaShip.getValue(), COMMA);
            for (String configId : ids) {
                Meta config = super.getMeta(Integer.valueOf(configId));
                if (config != null) {
                    configList.add(config);
                }
            }
            return configList;
        }

        @Override
        public List<Meta> listAllSubject(String orgId, Integer phaseId, Integer[] areaIds) {
            PtConfig orgSubjectShip = getConfigByOrg(orgId, phaseId);
            List<Meta> listAllSubjectByArea = listAllSubjectByArea(phaseId, areaIds);
            if (orgId == null) {
                return listAllSubjectByArea;
            }
            List<Meta> allConfigSubject = new ArrayList<Meta>();
            if (orgSubjectShip == null || StringUtils.isEmpty(orgSubjectShip.getValue())) {
                // 如果学校没有配置学科，则获取区域学科
                allConfigSubject = listAllSubjectByArea;
            } else {
                // 有则获取学校配置的学科
                allConfigSubject = listAllSubject(orgSubjectShip.getId());
                allConfigSubject.addAll(listAllSubjectByArea);
            }
            // 删除学校删除的学科
            Set<String> deleteSubject = new HashSet<String>();
            List<Meta> listMetaDeleteByOrg = listMetaDeleteByOrg(orgId, phaseId);
            if (listMetaDeleteByOrg != null && listMetaDeleteByOrg.size() > 0) {
                for (Meta meta : listMetaDeleteByOrg) {
                    deleteSubject.add(meta.getValue());
                }
            }

            List<Meta> allSubject = new ArrayList<Meta>();
            for (Meta meta : allConfigSubject) {
                if (!deleteSubject.contains(meta.getValue())) {
                    allSubject.add(meta);
                    deleteSubject.add(meta.getValue());
                }
            }
            return allSubject;
        }

        @Override
        public List<Meta> listAllSubjectByPhaseId(Integer phaseId) {
            Meta model = (Meta) super.getSysConfigByPhaseId(phaseId);
            return model == null ? null : listAllSubject(model.getId());
        }

        @Override
        protected String getCode() {
            return ConfigConstants.PHASE_SUBJECT_CODE;
        }

        /**
         * 获取区域学科
         *
         * @param phaseId
         *          学段id
         * @param areaIds
         *          区域id
         * @return List
         */
        public List<Meta> listAllSubjectByArea(Integer phaseId, Integer[] areaIds) {
            List<Meta> allConfigSubject = new ArrayList<Meta>();
            // 先获取各个区域配置的学科
            for (int i = 0; i < areaIds.length; i++) {
                PtConfig areaSubjectConfig = areaSubjectConfig(phaseId, areaIds[i]);
                if (areaSubjectConfig != null) {
                    allConfigSubject.addAll(listAllSubject(areaSubjectConfig.getId()));
                }
            }
            List<Meta> listAllSubjectByPhaseId = listAllSubjectByPhaseId(phaseId);
            if (listAllSubjectByPhaseId != null && listAllSubjectByPhaseId.size() > 0) {
                allConfigSubject.addAll(listAllSubjectByPhaseId);
            }

            // 删除区域删除的学科
            Set<String> deleteSubject = new HashSet<String>();
            for (int i = 0; i < areaIds.length; i++) {
                List<Meta> listMetaDeleteByArea = listMetaDeleteByArea(areaIds[i], phaseId);
                for (Meta meta : listMetaDeleteByArea) {
                    deleteSubject.add(meta.getValue());
                }
            }
            List<Meta> allSubject = new ArrayList<Meta>();
            for (Meta meta : allConfigSubject) {
                if (!deleteSubject.contains(meta.getValue())) {
                    allSubject.add(meta);
                    deleteSubject.add(meta.getValue());
                }
            }

            return allSubject;
        }

        protected PtConfig areaSubjectConfig(Integer phaseId, Integer areaId) {
            PtConfig model = new PtConfig();
            model.setAreaId(areaId);
            model.setPhase(phaseId);
            model.setType(ConfigConstants.AREA_TYPE);
            model.setCode(ConfigConstants.PHASE_SUBJECT_CODE);
            model.setEnable(1);
            return super.getSysConfig(model);
        }

        @Override
        public List<Meta> listAllSubjectMeta() {
            return super.listMeta(ConfigConstants.SYS_SUBJECT_CODE, ConfigConstants.SYS_TYPE);
        }

        @Override
        public List<Meta> listAllMeta(String orgId, Integer[] areaIds) {
            List<Meta> configs = new ArrayList<Meta>();
            // 系统学科元数据
            configs.addAll(listAllSysMeta());
            // 区域学科元数据
            List<Meta> metasArea = listAllMetaByArea(areaIds);
            configs.addAll(metasArea);
            if (orgId == null) {
                return configs;
            }
            // 获取学校自定义学科
            List<Meta> orgMetas = listMetaByOrg(orgId);
            configs.addAll(orgMetas);
            return configs;

        }

        protected List<Meta> listMetaByOrg(String orgId) {
           PtConfig model=new PtConfig();
           model.setOrgId(orgId);
           model.setCode(ConfigConstants.SYS_SUBJECT_CODE);
           model.setType(ConfigConstants.ORG_TYPE);
           model.setEnable(1);
            return super.listAll(model);
        }

        protected List<Meta> listMetaDeleteByOrg(String orgId, Integer phaseId) {
            PtConfig model=new PtConfig();
            model.setOrgId(orgId);
            model.setPhase(phaseId);
            model.setCode(ConfigConstants.SYS_SUBJECT_CODE);
            model.setType(ConfigConstants.ORG_TYPE);
            model.setEnable(0);
            return super.listAll(model);
        }

        protected List<Meta> listAllSysMeta() {
            // 所有系统元数据
            return listMeta(ConfigConstants.SYS_SUBJECT_CODE, ConfigConstants.SYS_TYPE);

        }

        // 根据区域ids获取出版社，（区域的话 areaIds为区域本身id和所有父级id；学校areaIds是机构表存的area_ids）
        protected List<Meta> listAllMetaByArea(Integer[] areaIds) {
            List<Meta> subjects = new ArrayList<Meta>();
            for (int i = 0; i < areaIds.length; i++) {
                // 获取区域自定义学科
                List<Meta> listMetaByArea = listMetaByArea(areaIds[i]);
                if (listMetaByArea != null && listMetaByArea.size() > 0) {
                    subjects.addAll(listMetaByArea);
                }
            }
            return subjects;
        }

        /**
         * 获取区域自定义学科
         *
         * @param areaId
         *          区域id
         * @return List
         */
        protected List<Meta> listMetaByArea(Integer areaId) {
            PtConfig model = new PtConfig();
            model.setAreaId(areaId);
            model.setEnable(1);
            model.setCode(ConfigConstants.SYS_SUBJECT_CODE);
            model.setType(ConfigConstants.AREA_TYPE);
            return super.listAll(model);
        }

        /**
         * 获取区域删除的学科
         *
         * @param areaId
         *          区域id
         * @param phaseId
         *          学段id 为null时查询所有删除的学科
         *
         * @return List
         */
        protected List<Meta> listMetaDeleteByArea(Integer areaId, Integer phaseId) {
            PtConfig model = new PtConfig();
            model.setAreaId(areaId);
            model.setPhase(phaseId);
            model.setEnable(0);
            model.setCode(ConfigConstants.SYS_SUBJECT_CODE);
            model.setType(ConfigConstants.AREA_TYPE);
            return super.listAll(model);
        }

        /**
         * 获取机构学科
         *
         * @param areaId
         *          区域id
         * @return List
         */
        public List<Meta> listAllSubjectMetaByOrg(Integer areaId) {
            List<Meta> configs = new ArrayList<Meta>();
            List<Meta> sysMetas = listMeta(ConfigConstants.SYS_SUBJECT_CODE, ConfigConstants.SYS_TYPE);
            List<Meta> areaMetas = listMeta(ConfigConstants.SYS_SUBJECT_CODE, ConfigConstants.AREA_TYPE);
            configs.addAll(sysMetas);
            configs.addAll(areaMetas);
            return configs;
        }

        @Override
        public PtConfig getConfigByOrg(String orgId, Integer phaseId) {
            PtConfig config = new PtConfig();
            config.setOrgId(orgId);
            config.setPhase(phaseId);
            config.setCode(ConfigConstants.PHASE_SUBJECT_CODE);
            config.setType(ConfigConstants.ORG_TYPE);
            config.setEnable(1);
            return super.getSysConfig(config);
        }

        @Override
        public PtConfig getConfigByArea(Integer areaId, Integer phaseId) {
            PtConfig config = new PtConfig();
            config.setAreaId(areaId);
            config.setPhase(phaseId);
            config.setCode(ConfigConstants.PHASE_SUBJECT_CODE);
            config.setType(ConfigConstants.AREA_TYPE);
            config.setEnable(1);
            return super.getSysConfig(config);
        }

    }
    @Component("phaseGradeProvider")
    public static class DefaultPhaseGradeProvider extends DefaultMetaProvider implements PhaseGradeProvider {

        @Override
        public List<Meta> listAllGrade(Integer id) {
            Meta sysconfig = super.getMeta(id);
            List<Meta> configList = new ArrayList<Meta>();
            String[] ids = StringUtils.split(sysconfig.getValue(), COMMA);
            for (String configId : ids) {
                Meta config = super.getMeta(Integer.valueOf(configId));
                if (config != null) {
                    configList.add(config);
                }
            }
            return configList;
        }

        @Override
        public List<Meta> listAllGradByPhaseId(Integer phaseId) {
            PtConfig model = super.getSysConfigByPhaseId(phaseId);
            return model == null ? null : listAllGrade(model.getId());
        }

        @Override
        protected String getCode() {
            return ConfigConstants.PHASE_GRADE_CODE;
        }

        @Override
        public List<Meta> listAllMeta() {
            return super.listGradeMeta();
        }

        @Override
        public List<Meta> listAllGradByPhaseIdAndCode(Integer phaseId, String code) {
            PtConfig model = new PtConfig();
            model.setCode(code);
            model.setPhase(phaseId);
            model.setType(getType());
            model = super.getSysConfig(model);
            return model == null ? null : listAllGrade(model.getId());
        }

    }
    @Component("xZGradeProvider")
    public static class DefaultXZGradeProvider extends DefaultMetaProvider implements XZGradeProvider {

        @Override
        public List<Meta> listAllGrade(Integer id) {
            Meta sysconfig = super.getMeta(id);
            List<Meta> configList = new ArrayList<Meta>();
            String[] ids = StringUtils.split(sysconfig.getValue(), COMMA);
            for (String configId : ids) {
                Meta config = super.getMeta(Integer.valueOf(configId));
                if (config != null) {
                    configList.add(config);
                }
            }
            return configList;
        }

        @Override
        public List<Meta> listAllGradByPhaseId(Integer phaseId) {
            PtConfig model = super.getSysConfigByPhaseId(phaseId);
            return model == null ? null : listAllGrade(model.getId());
        }

        @Override
        public List<Meta> listAllMeta() {
            return super.listGradeMeta();
        }

        @Override
        protected String getCode() {
            return ConfigConstants.XZ_GRADE_CODE;
        }

    }
    @Component("orgTypeProvider")
    public static class DefaultOrgTypeProvider extends DefaultMetaProvider implements OrgTypeProvider {

        @Override
        public List<Meta> listAllGrade(Integer id, Integer phaseId) {
            Map<Integer, List<Meta>> map = listPhaseGradeMap(id);
            List<Meta> rs = null;
            if (map == null) {
                rs = Collections.emptyList();
            } else {
                if (phaseId != null) {
                    rs = map.get(phaseId);
                } else {
                    rs = new ArrayList<>();
                    for (Integer key : map.keySet()) {
                        rs.addAll(map.get(key));
                    }
                }
            }
            return rs;
        }

        @Override
        public List<Meta> listAllPhase(Integer id) {
            Map<Integer, List<Meta>> phaseGradeMap = listPhaseGradeMap(id);
            List<Meta> configList = new ArrayList<Meta>();
            if (phaseGradeMap != null) {
                for (Integer key : phaseGradeMap.keySet()) {
                    configList.add(getMeta(key));
                }
            }
            return configList;
        }

        @Override
        @SuppressWarnings("unchecked")
        public Map<Integer, List<Meta>> listPhaseGradeMap(Integer id) {
            Meta sysConfig = super.getMeta(id);
            if (sysConfig != null) {
                Map<Integer, List<Meta>> phaseGradeMap = new TreeMap<Integer, List<Meta>>();
                if (StringUtils.isNotBlank(sysConfig.getValue())) {
                    List<Object> rs = (List<Object>) JSONUtils.parse(sysConfig.getValue());
                    for (Object object : rs) {
                        if (object instanceof Map) {
                            Map<String, List<Integer>> phaseInfos = (Map<String, List<Integer>>) object;
                            for (String k : phaseInfos.keySet()) {
                                List<Meta> configList = new ArrayList<Meta>();
                                for (Integer configId : phaseInfos.get(k)) {
                                    Meta meta = super.getMeta(configId);
                                    if (meta != null) {
                                        configList.add(meta);
                                    }
                                }

                                phaseGradeMap.put(Integer.valueOf(k), configList);
                            }
                        }
                    }
                }
                return phaseGradeMap;

            }
            return null;
        }

        @Override
        protected String getCode() {
            return ConfigConstants.ORG_TYPE_CODE;
        }

        @SuppressWarnings("unchecked")
        @Override
        public Map<Integer, List<Meta>> listPhaseXzGradeMap(Integer id) {
            PtConfig sysConfig = (PtConfig) super.getMeta(id);
            if (sysConfig != null) {
                Map<Integer, List<Meta>> phaseGradeMap = new HashMap<Integer, List<Meta>>();
                if (StringUtils.isNotBlank(sysConfig.getDomain())) {
                    List<Object> rs = (List<Object>) JSONUtils.parse(sysConfig.getDomain());
                    for (Object object : rs) {
                        if (object instanceof Map) {
                            Map<String, List<Integer>> phaseInfos = (Map<String, List<Integer>>) object;
                            for (String k : phaseInfos.keySet()) {
                                List<Meta> configList = new ArrayList<Meta>();
                                for (Integer configId : phaseInfos.get(k)) {
                                    Meta meta = super.getMeta(configId);
                                    if (meta != null) {
                                        configList.add(meta);
                                    }
                                }

                                phaseGradeMap.put(Integer.valueOf(k), configList);
                            }
                        }
                    }
                }
                return phaseGradeMap;

            }
            return null;
        }

        @Override
        public Map<Integer, Integer> listPhaseXzGradeCountMap(Integer id) {
            Map<Integer, List<Meta>> phaseGrades = listPhaseXzGradeMap(id);
            Map<Integer, Integer> gradeCountMap = new HashMap<Integer, Integer>();
            for (Integer phase : phaseGrades.keySet()) {
                gradeCountMap.put(phase, phaseGrades.get(phase).size());
            }

            return gradeCountMap;
        }

    }
    @Component("publisherProvider")
    public static class DefaultPublisherProvider extends DefaultMetaProvider implements PublisherProvider {

        @Override
        public List<Meta> listAllPublisher(Integer id) {
            Meta metaShip = super.getMeta(id);
            List<Meta> publisherList = new ArrayList<Meta>();
            String[] ids = StringUtils.split(metaShip.getValue(), COMMA);
            for (String configId : ids) {
                Meta config = super.getMeta(Integer.valueOf(configId));
                if (config != null) {
                    publisherList.add(config);
                }
            }
            return publisherList;
        }

        /**
         *
         * @param phaseId
         *          学段id
         * @param subjectId
         *          学科id
         * @param orgId
         *          机构id
         * @return List
         */
        @Override
        public List<Meta> listAllPublisher(Integer phaseId, Integer subjectId, String orgId, Integer[] areaIds) {
            List<Meta> listAllPublisherByArea = listAllPublisherByArea(phaseId, subjectId, areaIds);
            if (orgId == null) {
                // 如果orgId为null，则查询区域配置的出版社信息
                return listAllPublisherByArea;
            }
            // 获取学校配置的出版社关系
            Meta publishConfig = (Meta) getPublishConfig(phaseId, subjectId, orgId);
            List<Meta> publishers = new ArrayList<Meta>();
            publishers.addAll(listAllPublisherByArea);
            if (publishConfig != null) {
                // 如果有配置，则查询配置的出版社
                publishers.addAll(listAllPublisher(publishConfig.getId()));

            }
            // 删除机构删除的出版社
            List<Meta> deletes = listMetaDeleteByOrg(phaseId, subjectId, orgId);
            Set<String> deleteIds = new HashSet<String>();
            for (Meta sysConfig : deletes) {
                deleteIds.add(sysConfig.getValue());
            }

            // 删除后可用的出版社
            List<Meta> enableList = new ArrayList<Meta>();

            for (Meta sysConfig : publishers) {
                if (!deleteIds.contains(sysConfig.getValue())) {
                    enableList.add(sysConfig);
                    deleteIds.add(sysConfig.getValue());
                }
            }
            return enableList;
        }

        @Override
        public List<Meta> listAllByPhaseAndSubject(Integer phaseId, Integer subjectId) {
            Meta sysConfig = (Meta) getPublishConfig(phaseId, subjectId);
            List<Meta> publishers = new ArrayList<Meta>();
            if (sysConfig != null) {
                String value = sysConfig.getValue();
                String[] split = value.split(COMMA);
                for (String id : split) {
                    if (StringUtils.isEmpty(id)) {
                        continue;
                    }
                    Meta config = super.getMeta(Integer.valueOf(id));
                    publishers.add(config);
                }

            }
            return publishers;
        }

        @Override
        protected String getCode() {
            return ConfigConstants.PHASE_SUBJECT_PUBLISHER_CODE;
        }

        @Override
        public List<Meta> listAllPublisherMeta() {
            return super.listMeta(ConfigConstants.SYS_PUBLISHER_CODE, ConfigConstants.SYS_TYPE);
        }

        // 系统所有出版社元数据
        protected List<Meta> listAllSysMeta() {
            return listMeta(ConfigConstants.SYS_PUBLISHER_CODE, ConfigConstants.SYS_TYPE);

        }

        // 根据区域ids获取出版社，（区域的话 areaIds为区域本身id和所有父级id；学校areaIds是机构表存的area_ids）
        protected List<Meta> listAllMetaByArea(Integer[] areaIds) {
            List<Meta> configs = new ArrayList<Meta>();
            // 获取区域自定义出版社
            for (int i = 0; i < areaIds.length; i++) {
                List<Meta> listMetaByArea = listMetaByArea(areaIds[i]);
                if (listMetaByArea != null && listMetaByArea.size() > 0) {
                    configs.addAll(listMetaByArea);
                }
            }
            return configs;
        }

        // 获取单个区域自定义出版社元数据
        List<Meta> listMetaByArea(Integer areaId) {
            PtConfig model = new PtConfig();
            model.setAreaId(areaId);
            model.setEnable(1);
            model.setCode(ConfigConstants.SYS_PUBLISHER_CODE);
            model.setType(ConfigConstants.AREA_TYPE);
            return super.listAll(model);
        }

        // 获取区域自定义出版社元数据
        List<Meta> listMetaByOrg(String orgId) {
            PtConfig model = new PtConfig();
            model.setOrgId(orgId);
            model.setEnable(1);
            model.setCode(ConfigConstants.SYS_PUBLISHER_CODE);
            model.setType(ConfigConstants.ORG_TYPE);
            return super.listAll(model);
        }

        @Override
        public List<Meta> listAllMeta(String orgId, Integer[] areaIds) {
            List<Meta> configs = new ArrayList<Meta>();
            // 获取系统出版社元数据
            List<Meta> listAllSysMeta = listAllSysMeta();
            configs.addAll(listAllSysMeta);
            // 区域自定义出版社，已包含系统
            List<Meta> metasArea = listAllMetaByArea(areaIds);
            configs.addAll(metasArea);
            if (orgId == null) {
                return configs;
            }
            // 学校自定义的出版社元数据
            List<Meta> listMetaByOrg = listMetaByOrg(orgId);
            configs.addAll(listMetaByOrg);
            return configs;
        }

        @Override
        public PtConfig getPublishConfig(Integer phaseId, Integer subjectId) {
            PtConfig model = new PtConfig();
            model.setPhase(phaseId);
            model.setSubjectId(subjectId);
            model.setCode(getCode());
            model.setType(getType());
            model.setEnable(1);
            return super.getSysConfig(model);
        }

        @Override
        public PtConfig getPublishConfig(Integer phaseId, Integer subjectId, String orgId) {
            PtConfig model = new PtConfig();
            model.setPhase(phaseId);
            model.setSubjectId(subjectId);
            model.setOrgId(orgId);
            model.setCode(getCode());
            model.setType(ConfigConstants.ORG_TYPE);
            model.setEnable(1);
            return super.getSysConfig(model);
        }

        @Override
        public PtConfig getPublishConfig(Integer phaseId, Integer subjectId, Integer areaId) {
            PtConfig model = new PtConfig();
            model.setPhase(phaseId);
            model.setSubjectId(subjectId);
            model.setAreaId(areaId);
            model.setCode(getCode());
            model.setType(ConfigConstants.AREA_TYPE);
            model.setEnable(1);
            return super.getSysConfig(model);
        }

        /**
         * 获取区域出版社
         *
         * @param phaseId
         *          学段id
         * @param subjectId
         *          学科id
         * @param areaIds
         *          区域id数组
         * @return List
         */
        public List<Meta> listAllPublisherByArea(Integer phaseId, Integer subjectId, Integer[] areaIds) {
            List<Meta> publishers = new ArrayList<Meta>();
            publishers.addAll(listAllByPhaseAndSubject(phaseId, subjectId));
            for (int i = 0; i < areaIds.length; i++) {
                Meta publishConfig = (Meta) getPublishConfig(phaseId, subjectId, areaIds[i]);
                if (publishConfig != null) {
                    publishers.addAll(listAllPublisher(publishConfig.getId()));
                }
            }

            // 删除区域删除的学科
            Set<String> deleteIds = new HashSet<String>();
            for (int i = 0; i < areaIds.length; i++) {
                List<Meta> listMetaDeleteByArea = listMetaDeleteByArea(phaseId, subjectId, areaIds[i]);
                for (Meta meta : listMetaDeleteByArea) {
                    deleteIds.add(meta.getValue());
                }
            }
            List<Meta> enableList = new ArrayList<Meta>();
            for (Meta sysConfig : publishers) {
                if (!deleteIds.contains(sysConfig.getValue())) {
                    enableList.add(sysConfig);
                    deleteIds.add(sysConfig.getValue());
                }
            }
            return enableList;
        }

        protected List<Meta> listMetaDeleteByOrg(Integer phaseId, Integer subjectId, String orgId) {
            PtConfig config = new PtConfig();
            config.setPhase(phaseId);
            config.setSubjectId(subjectId);
            config.setOrgId(orgId);
            config.setEnable(0);
            config.setCode(ConfigConstants.SYS_PUBLISHER_CODE);
            config.setType(ConfigConstants.ORG_TYPE);
            return super.listAll(config);
        }

        protected List<Meta> listMetaDeleteByArea(Integer phaseId, Integer subjectId, Integer areaId) {
            PtConfig config = new PtConfig();
            config.setPhase(phaseId);
            config.setSubjectId(subjectId);
            config.setAreaId(areaId);
            config.setEnable(0);
            config.setCode(ConfigConstants.SYS_PUBLISHER_CODE);
            config.setType(ConfigConstants.AREA_TYPE);
            return super.listAll(config);
        }

    }
    @Component("sysConfigProvider")
    public static class DefaultSysConfigProvider extends DefaultMetaProvider implements SysConfigProvider {

        @Override
        public List<Meta> listAllConfig() {
            PtConfig config = new PtConfig();
            config.setType(ConfigConstants.DOMIN_TYPE);
            return super.listAll(config);
        }

        @Override
        protected String getCode() {
            return null;
        }

        @Override
        public Meta getConfigByName(String code, String name) {
            PtConfig model = new PtConfig();
            model.setCode(code);
            model.setType(ConfigConstants.SYS_TYPE);
            model.setName(name);
            return (Meta) super.getSysConfig(model);
        }


        @Override
        public Meta getConfigByCondition(String code, String name,PtConfig config) {
            PtConfig model = new PtConfig();
            model.setCode(code);
            model.setOrgId(config.getOrgId());
            model.setName(name);
            return (Meta) super.getSysConfig(model);
        }
        @Override
        public Meta getConfigByNameWithDomain(String code, String name, String domain) {
            if (domain == null) {
                return getConfigByName(code, name);
            }
            PtConfig model = new PtConfig();
            model.setType(ConfigConstants.DOMIN_TYPE);
            model.setCode(code);
            model.setName(name);
            model.setDomain(domain);
            Meta sysConfig = (Meta) super.getSysConfig(model);
            if (sysConfig == null) {
                return getConfigByName(code, name);
            }
            return sysConfig;
        }
        @Override
        public Meta getConfigByNameWithDomain(String code, String name, String domain,String orgId) {
            if (domain == null) {
                return getConfigByName(code, name);
            }
            PtConfig model = new PtConfig();
            model.setType(ConfigConstants.DOMIN_TYPE);
            model.setCode(code);
            model.setName(name);
            model.setOrgId(orgId);
            model.setDomain(domain);
            Meta sysConfig = (Meta) super.getSysConfig(model);
            if (sysConfig == null) {
                return getConfigByName(code, name);
            }
            return sysConfig;
        }
    }
    @Component("bookEditionProvider")
    public static class DefaultBookEditionProvider extends DefaultMetaProvider implements BookEditionProvider {

        @Override
        protected String getCode() {
            return ConfigConstants.SYS_BOOKEDITION_CODE;
        }

        @Override
        public List<Meta> getALlEdition(Integer phaseId, Integer subjectId, Integer gradeId) {
            PtConfig model = new PtConfig();
            model.setPhase(phaseId);
            model.setSubjectId(subjectId);
            model.setGradeId(gradeId);
            model.setCode(getCode());
            model.setType(getType());
            model.setEnable(1);
            return super.listAll(model);

        }

        @Override
        public PtConfig getEdition(Integer phaseId, Integer subjectId, Integer gradeId) {
            List<Meta> aLlEdition = getALlEdition(phaseId, subjectId, gradeId);
            if (aLlEdition != null && aLlEdition.size() > 0) {
                return (PtConfig) aLlEdition.get(0);

            }
            return null;
        }

        List<Meta> getAllEdititonByPhases(Set<Integer> phase, Integer subjectId, Integer gradeId) {
            EntityWrapper<PtConfig> wrapper=new EntityWrapper<>();
            wrapper.in("phases",phase);
            wrapper.eq("subject_id",subjectId);
            wrapper.eq("grade_id",gradeId);
            wrapper.eq("code",getCode());
            wrapper.eq("type",getType());
            List<Meta> list=new ArrayList<Meta>();
            List<PtConfig> ptConfigs = super.configMapper.selectList(wrapper);
            list.addAll(ptConfigs);
            return list;
        }


        @Override
        public List<Meta> getAllEditionWithSchool(Integer phaseId, Integer subjectId, Integer gradeId, String orgId) {
            PtConfig model = new PtConfig();
            model.setSubjectId(subjectId);
            model.setGradeId(gradeId);
            model.setOrgId(orgId);
            model.setCode(getCode());
            model.setPhase(phaseId);
            model.setEnable(1);
            model.setType(ConfigConstants.ORG_TYPE);
            // 学校教材版本
            List<Meta> listAll = listAll(model);
            List<Meta> sysEditions = new ArrayList<Meta>();
            if (phaseId == null) {
                List<Meta> listAllPhase = MetaUtils.getOrgTypeProvider().listAllPhase(orgMapper.selectById(orgId).getSchoolings());
                Set<Integer> phases = new HashSet<Integer>();
                for (Meta meta : listAllPhase) {
                    phases.add(meta.getId());
                }
                sysEditions = getAllEdititonByPhases(phases, subjectId, gradeId);
            } else {
                sysEditions = getALlEdition(phaseId, subjectId, gradeId);
            }
            Set<Integer> delEditions = new HashSet<Integer>();
            List<Meta> orgDelSysEdition = getOrgDelSysEdition(phaseId, subjectId, gradeId, orgId);
            for (Meta meta : orgDelSysEdition) {
                delEditions.add(Integer.valueOf(meta.getValue()));
            }
            List<Meta> allEditions = new ArrayList<Meta>();
            allEditions.addAll(listAll);
            Set<String> schoolEditionKeys = new HashSet<String>();
            if (listAll != null && listAll.size() > 0) {
                for (Meta meta : listAll) {
                    PtConfig orgConfig = (PtConfig) meta;
                    schoolEditionKeys
                            .add("p_" + orgConfig.getPhase() + "_s_" + orgConfig.getSubjectId() + "_g_" + orgConfig.getGradeId());
                }
            }
            processEdition(schoolEditionKeys, sysEditions, delEditions, allEditions);
            return allEditions;
        }

        private void processEdition(Set<String> schoolEditionKeys, List<Meta> sysEditions, Set<Integer> delEditions,
                                    List<Meta> allEditions) {
            if (sysEditions != null) {
                for (Meta meta : sysEditions) {
                    PtConfig orgConfig = (PtConfig) meta;
                    if (delEditions.contains(meta.getId()) || schoolEditionKeys.contains(
                            "p_" + orgConfig.getPhase() + "_s_" + orgConfig.getSubjectId() + "_g_" + orgConfig.getGradeId())) {
                        continue;
                    }
                    allEditions.add(meta);
                }
            }
        }

        protected List<Meta> getOrgDelSysEdition(Integer phaseId, Integer subjectId, Integer gradeId, String orgId) {
            PtConfig model = new PtConfig();
            model.setPhase(phaseId);
            model.setSubjectId(subjectId);
            model.setGradeId(gradeId);
            model.setOrgId(orgId);
            model.setCode(getCode());
            model.setEnable(0);
            model.setType(ConfigConstants.ORG_TYPE);
            return listAll(model);
        }

        @Override
        public Meta getEditionWithSchool(Integer phaseId, Integer subjectId, Integer gradeId, String orgId) {
            List<Meta> allEditionWithSchool = getAllEditionWithSchool(phaseId, subjectId, gradeId, orgId);
            if (allEditionWithSchool != null && allEditionWithSchool.size() > 0) {
                return allEditionWithSchool.get(0);
            }
            return null;

        }

    }
    @Component("appTypeProvider")
    public static class DefaultAppTypeProvider extends DefaultMetaProvider implements AppTypeProvider {

        @Override
        public List<Meta> getAllAppType() {
            return super.listAll();
        }

        @Override
        protected String getCode() {
            return ConfigConstants.SYS_APPTYPE_CODE;
        }

    }
    @Component("unitTypeProvider")
    public static class DefaultUnitTypeProvider extends DefaultMetaProvider implements UnitTypeProvider {

        @Override
        public List<Meta> getAllUnitType() {
            return super.listAll();
        }

        @Override
        protected String getCode() {
            return ConfigConstants.SYS_UNIT_CODE;
        }

    }
    @Component("schoolYearProvider")
    public static class DefaultSchoolYearProvider extends DefaultMetaProvider implements SchoolYearProvider {

        @Override
        public List<Meta> getAllSchoolYear() {
            return super.listAll();
        }

        @Override
        protected String getCode() {
            return ConfigConstants.SCHOOLYEAR_CODE;
        }

        @Override
        public List<Meta> getSchoolYearWithOrg(String orgId) {
            PtConfig model = new PtConfig();
            model.setType(ConfigConstants.ORG_TYPE);
            model.setCode(ConfigConstants.SCHOOLYEAR_CODE);
            model.setOrgId(orgId);
            return super.listAll(model);
        }

        @Override
        public List<Meta> getSchoolYearWithOrgAndArea(String orgId) {
            List<Meta> scList = new ArrayList<Meta>();
            List<Meta> orgScList = getSchoolYearWithOrg(orgId);
            scList.addAll(orgScList);
            String areaIds = orgMapper.selectById(orgId).getAreaIds();
            String subAreaIds = areaIds.substring(1, areaIds.length() - 1);
            String[] areaIdsArr = subAreaIds.split(COMMA);
            Set<Integer> yearSet = new HashSet<Integer>();
            for (Meta year : orgScList) {
                PtConfig conf = (PtConfig) year;
                yearSet.add(conf.getPhase());
            }
            for (int i = 0; i < areaIdsArr.length; i++) {
                List<Meta> schoolYearWithArea = getSchoolYearWithArea(Integer.valueOf(areaIdsArr[i]));
                for (Meta meta : schoolYearWithArea) {
                    PtConfig conf = (PtConfig) meta;
                    if (yearSet.contains(conf.getPhase())) {
                        continue;
                    }
                    scList.add(meta);
                    yearSet.add(conf.getPhase());
                }
            }
            return scList;
        }

        @Override
        public List<Meta> getTerm(Integer schoolYearId) {
            PtConfig model = new PtConfig();
            // 借用phase表示学年
            model.setPhase(schoolYearId);
            model.setCode(ConfigConstants.TERM_CODE);
            model.setType(ConfigConstants.ORG_TYPE);
            return  super.listAllNoOrg(model);
        }

        @Override
        public List<Meta> getSchoolYearWithArea(Integer areaId) {
            PtConfig model = new PtConfig();
            model.setType(ConfigConstants.AREA_TYPE);
            model.setCode(ConfigConstants.SCHOOLYEAR_CODE);
            model.setAreaId(areaId);
            return super.listAll(model);
        }

        @Override
        public Integer getCurrentSchoolYear() {
            int m = 7; // 默认月
            int d = 31;// 默认天
            try {
                PtConfig model = new PtConfig();
                model.setCode(ConfigConstants.PLATFORM_EXT_CONFIG_CODE);
                model.setName(MetaKeys.SCHOOL_YEAR_SPLIT);
                model.setEnable(1);
                PtConfig meta = super.getSysConfig(model);
                if (meta != null) {
                    String[] md = meta.getValue().trim().split("\\.");
                    m = Integer.valueOf(md[0]);
                    d = Integer.valueOf(md[1]);
                }
            } catch (Exception e) {
                // do nothing
            }
            Calendar c = Calendar.getInstance();
            int year = c.get(Calendar.YEAR);
            int month = c.get(Calendar.MONTH) + 1;// 生活中实际的月份
            if (month < m || (m == month && c.get(Calendar.DAY_OF_MONTH) < d)) {
                year--;
            }
            return year;
        }

        /**
         * @param orgId
         *          机构id
         */
        @Override
        public Integer getCurrentSchoolYear(String orgId) {
            Integer currentYear = getCurrentYear(ConfigConstants.ORG_TYPE, orgId, null);
            return currentYear != null ? currentYear : getCurrentSchoolYear();
        }

        @Override
        public Integer getCurrentSchoolYear(Integer areaId) {
            Integer currentYear = getCurrentYear(ConfigConstants.AREA_TYPE, null, areaId);
            return currentYear != null ? currentYear : getCurrentSchoolYear();
        }

        private Integer getCurrentYear(String type, String orgId, Integer areaId) {
            if (StringUtils.isEmpty(type)) {
                return getCurrentSchoolYear();
            }
            Calendar c = Calendar.getInstance();
            Integer year = c.get(Calendar.YEAR);
            EntityWrapper<PtConfig> model = new EntityWrapper<>();
            model.eq("type",type);
            model.eq("phase",year);
            model.eq("code",ConfigConstants.SCHOOLYEAR_CODE);
            if (ConfigConstants.ORG_TYPE.equals(type)) {
                if (StringUtils.isEmpty(orgId)) {
                    return getCurrentSchoolYear();
                }
                model.eq("org_id",orgId);
            }
            if (ConfigConstants.AREA_TYPE.equals(type)) {
                if (areaId == null) {
                    return getCurrentSchoolYear();
                }
                model.eq("area_id",areaId);
            }
            PtConfig cf = super.listOne(model);
            if (cf != null) {
                String[] date = cf.getValue().split("-");// 2016.09.01
                if (date != null && date.length > 0) {
                    try {
                        Calendar cu = Calendar.getInstance();
                        Date dd = DateUtils.parseDate(date[0], "yyyy.MM.dd");
                        cu.setTime(dd);
                        if (c.after(cu)) {
                            return cf.getPhase();
                        } else {
                            return cf.getPhase() - 1;
                        }
                    } catch (ParseException e) {
                        logger.error("get current schoolYear failed");
                    }
                }
            } else {
                if (ConfigConstants.ORG_TYPE.equals(type)) {
                    PtOrg organization = orgMapper.selectById(orgId);
                    if (organization == null) {
                        return getCurrentSchoolYear();
                    }
                    return getCurrentYear(ConfigConstants.AREA_TYPE, null, organization.getAreaId());
                }
            }
            return null;
        }

    }
}
